package client.gui;

import client.ClientHandler;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import util.pref.PrefHandler;

/**
 * GUI of the editor.
 * @author ernesta
 */
public class Editor2 extends JFrame {
    private final String APP = "Versi";
    
    private HashMap<String, String[]> fileMap;
    private HashMap<String, String> userMap;
    
    private static Editor2 editor;
    private static ClientHandler clientHandler;
    
    private static String currentFile;
    private static Queue<String> notifQueue;

    
    /** Creates new form Editor */
    public Editor2() {
        initComponents();
        checkIfFirstTime();
        
        //For testing purposes
        initMap();
        updateFileList(fileMap);
        updateUserList(userMap);
        //END for testing purposes
        
        initFileTree();
        initUserTree();
    }
    
    
    public static Editor2 getInstance() {
        return editor;
    }
    
    
    /**
     * No comment.
     * @param args 
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Editor.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Editor.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Editor.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Editor.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                editor = new Editor2();
                try {
                    clientHandler = new ClientHandler();
                } catch (RemoteException ex) {
                    System.out.println(ex);
                } catch (NotBoundException ex) {
                    System.out.println(ex);
                }
                
                currentFile = "";
                notifQueue = new LinkedList<String>();
                
                Toolkit toolkit = Toolkit.getDefaultToolkit();
                Dimension screen = toolkit.getScreenSize();
                
                int x = (screen.width - editor.getWidth()) / 2;
                int y = (screen.height - editor.getHeight()) / 2;
                editor.setLocation(x, y);
                
                editor.setVisible(true);
            }
        });
    }
     
    
    /**
     * A test method for our file list.
     * To be removed.
     */
    private void initMap() {
        String[] list = {"locked", "ernesta"};
        fileMap = new HashMap<String, String[]>();
        fileMap.put("hello.php", list);
        fileMap.put("yeah.txt", list);
        
        userMap = new HashMap<String, String>();
        userMap.put("ernesta", "online");
        userMap.put("robert", "offline");
        userMap.put("a", "online");
        userMap.put("b", "offline");
        userMap.put("c", "online");
        userMap.put("d", "offline");
        userMap.put("e", "online");
        userMap.put("f", "offline");
    }
    
    
    private void checkIfFirstTime() {
        PrefHandler prefHandler = new PrefHandler();
        String[] keys = {"FIRST_TIME"};
        HashMap<String, String> oldPreferences = prefHandler.getPreferences(keys);
        
        String first = "";
        if (oldPreferences != null) {
            first = oldPreferences.get(keys[0]);
        }
        
        if (first.equals("true")) {
            HashMap<String, String> newPreferences = new HashMap();
            newPreferences.put(keys[0], "false");
            prefHandler.setPreferences(newPreferences);
            
            showPreferencesDialog();
        }
    }
    
    
    /**
     * Update the editor's notification bar.
     * @param message to be displayed to the user
     */
    public void updateNotificationBar(String message) {
        notifQueue.offer(message);
        
        if (notifQueue.size() > 5) {
            notifQueue.remove();
        }
        
        notificationBar.setText(message);
    }
    
    
    /**
     * Update the editor's remote file list.
     * @param map of remote files and related data.
     */
    public final void updateFileList(HashMap<String, String[]> map) {
        fileMap = map;
        removeCurrentNodes(fileTree);
        addNewNodes(fileTree, fileMap);
    }
    
    
    /**
     * Update the editor's user list.
     * @param map of all the users
     */
    public final void updateUserList(HashMap<String, String> map) {
        userMap = map;
        removeCurrentNodes(userTree);
        addNewNodes(userTree, userMap);
    }
    
    
    /**
     * Initialize the remote file tree.
     * http://download.oracle.com/javase/1.4.2/docs/api/javax/swing/JTree.html
     */
    private void initFileTree() {
        fileTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        
        MouseListener mouseListener = new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent evt) {
                int selectedRow = fileTree.getRowForLocation(evt.getX(), evt.getY());
                TreePath selectedPath = fileTree.getPathForLocation(evt.getX(), evt.getY());
                
                if (selectedRow != -1) {
                    DefaultMutableTreeNode node = (DefaultMutableTreeNode)selectedPath.getLastPathComponent();
                    
                    String file = node.toString();
                    String status = fileMap.get(file)[0];
                    String user = fileMap.get(file)[1];
                    updateNotificationBar(file + " is " + status + " by " + user + ".");
                    
                    if (evt.getClickCount() != 1) openRemoteFile(node.toString());
                }
            }
        };
        
        fileTree.addMouseListener(mouseListener);
    }
    
    
    private void initUserTree() {
        userTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        userTree.addTreeSelectionListener(new TreeSelectionListener() {
            @Override
            public void valueChanged(TreeSelectionEvent evt) {
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) evt.getPath().getLastPathComponent();
                
                String user = node.toString();
                String status = userMap.get(user);
                String message = " is currently ";
                updateNotificationBar(user + message + status + ".");
            }
        });
    }
    
    
    /**
     * Ask ClientHandler to open a remote file.
     */
    private void openRemoteFile(String filename) {
        int result = 0;
        try {
            result = clientHandler.checkOut(filename);
        } catch (RemoteException ex) {
            Logger.getLogger(Editor2.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            Logger.getLogger(Editor2.class.getName()).log(Level.SEVERE, null, ex);
        }
        if (result == 0) {
            updateNotificationBar("Checkout unsuccessful.");
        } else if (result == 1) {
            updateNotificationBar("The file is locked.");
            currentFile = filename;
            editArea.setEditable(false);
        } else {
            editArea.setEditable(true);
        }
    }
    
    
    /**
     * Add new nodes to a tree from a given HashMap.
     * @param tree
     * @param map 
     */
    private void addNewNodes(JTree tree, HashMap map) {
        DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
        MutableTreeNode root = (MutableTreeNode)model.getRoot();
        Map.Entry pairs = null;
        
        Iterator i = map.entrySet().iterator();
        while(i.hasNext()) {
            pairs = (Map.Entry)i.next();
            MutableTreeNode node = new DefaultMutableTreeNode(pairs.getKey());
            model.insertNodeInto(node, root, root.getChildCount());
        }
        
        tree.expandRow(0);
    }
    
    
    /**
     * Remove nodes from the remote file tree to free up space for a new list.
     */
    private void removeCurrentNodes(JTree tree) {
        DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
        MutableTreeNode node = (MutableTreeNode)model.getRoot();
        
        Enumeration<DefaultMutableTreeNode> children = node.children();
        List<DefaultMutableTreeNode> childList = new ArrayList<DefaultMutableTreeNode>();
        
        while (children.hasMoreElements()) {
            DefaultMutableTreeNode child = children.nextElement();
            childList.add(child);
        }
        
        for (MutableTreeNode mutableTreeNode: childList) {
            model.removeNodeFromParent(mutableTreeNode);
        }
    }
    
    
    /**
     * Shows a preferences dialog.
     */
    private void showPreferencesDialog() {
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                Options options = new Options();
                
                Toolkit toolkit = Toolkit.getDefaultToolkit();
                Dimension screen = toolkit.getScreenSize();
                
                int x = (screen.width - options.getWidth()) / 2;
                int y = (screen.height - options.getHeight()) / 2;
                options.setLocation(x, y);
                
                options.setVisible(true);
            }
        });
    }
    
    
    /**
     * Shows a dialog on exit.
     */
    private void showExitDialog() {
        String message = "Do you want to save and commit the file before closing Versi?";
        Object[] options = {"Cancel", "Save and commit", "Just save"};
        int choice = JOptionPane.showOptionDialog(
                    this,
                    message,
                    APP,
                    JOptionPane.YES_NO_CANCEL_OPTION,
                    JOptionPane.PLAIN_MESSAGE, null,
                    options,
                    options[1]);
        
        if (choice == JOptionPane.CANCEL_OPTION) {
            saveOpenFile();
        } else if (choice == JOptionPane.NO_OPTION) {
            saveOpenFile();
            try {
                clientHandler.checkIn(currentFile);
            } catch (RemoteException ex) {
                System.out.println(ex);
            } catch (FileNotFoundException ex) {
                System.out.println(ex);
            } catch (Exception ex) {
                System.out.println(ex);
            }
        }
    }
    
    
    private void saveOpenFile() {
        File file = null;
        
        if (currentFile.equals("")) {
            int returnVal = fileChooser.showSaveDialog(this);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                file = fileChooser.getSelectedFile();
            }
        } else {
            file = new File(currentFile);
        }
        
        try {
            FileWriter writer = new FileWriter(file);
            editArea.write(writer);
            updateNotificationBar("File saved.");
        } catch (IOException ex) {
            updateNotificationBar("Error writing file.");
        }
    }
    

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        fileChooser = new javax.swing.JFileChooser();
        optionPane = new javax.swing.JOptionPane();
        areaScroll = new javax.swing.JScrollPane();
        editArea = new javax.swing.JTextArea();
        notificationBar = new javax.swing.JLabel();
        treeScroll = new javax.swing.JScrollPane();
        fileTree = new javax.swing.JTree();
        treeScroll1 = new javax.swing.JScrollPane();
        userTree = new javax.swing.JTree();
        jMenuBar1 = new javax.swing.JMenuBar();
        menuFile = new javax.swing.JMenu();
        menuNew = new javax.swing.JMenuItem();
        menuOpen = new javax.swing.JMenuItem();
        menuSave = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();
        menuExit = new javax.swing.JMenuItem();
        menuEdit = new javax.swing.JMenu();
        menuCut = new javax.swing.JMenuItem();
        menuCopy = new javax.swing.JMenuItem();
        menuPaste = new javax.swing.JMenuItem();
        menuVersion = new javax.swing.JMenu();
        menuCommit = new javax.swing.JMenuItem();
        menuPrefs = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Versi");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        editArea.setColumns(20);
        editArea.setRows(5);
        areaScroll.setViewportView(editArea);

        notificationBar.setText("Versi");
        notificationBar.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                notificationBarMouseReleased(evt);
            }
        });

        javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("Files");
        fileTree.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
        treeScroll.setViewportView(fileTree);

        treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("Users");
        userTree.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
        treeScroll1.setViewportView(userTree);

        menuFile.setText("File");

        menuNew.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.event.InputEvent.CTRL_MASK));
        menuNew.setText("New");
        menuNew.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuNewActionPerformed(evt);
            }
        });
        menuFile.add(menuNew);

        menuOpen.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK));
        menuOpen.setText("Open");
        menuOpen.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuOpenActionPerformed(evt);
            }
        });
        menuFile.add(menuOpen);

        menuSave.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK));
        menuSave.setText("Save");
        menuSave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuSaveActionPerformed(evt);
            }
        });
        menuFile.add(menuSave);
        menuFile.add(jSeparator1);

        menuExit.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F4, java.awt.event.InputEvent.ALT_MASK));
        menuExit.setText("Exit");
        menuExit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuExitActionPerformed(evt);
            }
        });
        menuFile.add(menuExit);

        jMenuBar1.add(menuFile);

        menuEdit.setText("Edit");

        menuCut.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_X, java.awt.event.InputEvent.CTRL_MASK));
        menuCut.setText("Cut");
        menuCut.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuCutActionPerformed(evt);
            }
        });
        menuEdit.add(menuCut);

        menuCopy.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_C, java.awt.event.InputEvent.CTRL_MASK));
        menuCopy.setText("Copy");
        menuCopy.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuCopyActionPerformed(evt);
            }
        });
        menuEdit.add(menuCopy);

        menuPaste.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_V, java.awt.event.InputEvent.CTRL_MASK));
        menuPaste.setText("Paste");
        menuPaste.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuPasteActionPerformed(evt);
            }
        });
        menuEdit.add(menuPaste);

        jMenuBar1.add(menuEdit);

        menuVersion.setText("Version Control");

        menuCommit.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_M, java.awt.event.InputEvent.CTRL_MASK));
        menuCommit.setText("Commit");
        menuCommit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuCommitActionPerformed(evt);
            }
        });
        menuVersion.add(menuCommit);

        menuPrefs.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_P, java.awt.event.InputEvent.CTRL_MASK));
        menuPrefs.setText("Preferences");
        menuPrefs.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuPrefsActionPerformed(evt);
            }
        });
        menuVersion.add(menuPrefs);

        jMenuBar1.add(menuVersion);

        setJMenuBar(jMenuBar1);

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .add(areaScroll, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 428, Short.MAX_VALUE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
                            .add(treeScroll1)
                            .add(treeScroll, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 179, Short.MAX_VALUE)))
                    .add(notificationBar))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                    .add(layout.createSequentialGroup()
                        .add(treeScroll, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 314, Short.MAX_VALUE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(treeScroll1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 120, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                    .add(areaScroll, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 442, Short.MAX_VALUE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(notificationBar)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    
    /**
     * Save a file.
     * @param evt 
     */
    private void menuSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuSaveActionPerformed
        saveOpenFile();
    }//GEN-LAST:event_menuSaveActionPerformed

    
    /**
     * Open a file for reading.
     * @param evt 
     */
    private void menuOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuOpenActionPerformed
        int returnVal = fileChooser.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fileChooser.getSelectedFile();
            try {
                currentFile = file.getAbsolutePath();
                editArea.read(new FileReader(currentFile), null);
                editArea.setEditable(true);
                
                updateNotificationBar("File opened.");
            } catch (IOException ex) {
                updateNotificationBar("Error reading file.");
            }
        }
    }//GEN-LAST:event_menuOpenActionPerformed
    
    
    /**
     * Cut selected text.
     * @param evt 
     */
    private void menuCutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuCutActionPerformed
        editArea.cut();
    }//GEN-LAST:event_menuCutActionPerformed
    
    
    /**
     * Copy selected text.
     * @param evt 
     */
    private void menuCopyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuCopyActionPerformed
        editArea.copy();
    }//GEN-LAST:event_menuCopyActionPerformed

    
    /**
     * Paste cut/copied text.
     * @param evt 
     */
    private void menuPasteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuPasteActionPerformed
        editArea.paste();
    }//GEN-LAST:event_menuPasteActionPerformed

    
    /**
     * Create a new text file.
     * @param evt 
     */
    private void menuNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuNewActionPerformed
        editArea.setText("");
        editArea.setEditable(true);
        
        currentFile = "";
        updateNotificationBar("New file started.");
    }//GEN-LAST:event_menuNewActionPerformed

    
    /**
     * Commit a file.
     * @param evt 
     */
    private void menuCommitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuCommitActionPerformed
        saveOpenFile();
        try {
            clientHandler.checkIn(currentFile);
        } catch (RemoteException ex) {
            System.out.println(ex);
        } catch (FileNotFoundException ex) {
            System.out.println(ex);
        } catch (Exception ex) {
            System.out.println(ex);
        }
    }//GEN-LAST:event_menuCommitActionPerformed

    
    /**
     * Open a preferences dialog.
     * @param evt 
     */
    private void menuPrefsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuPrefsActionPerformed
        showPreferencesDialog();
    }//GEN-LAST:event_menuPrefsActionPerformed

    
    /**
     * Allows exiting the system from the menu.
     * @param evt 
     */
    private void menuExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuExitActionPerformed
        System.exit(0);
    }//GEN-LAST:event_menuExitActionPerformed

    
    /**
     * Asks if a particular file should be saved and committed before exiting.
     * @param evt 
     */
    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        showExitDialog();
    }//GEN-LAST:event_formWindowClosing

    private void notificationBarMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_notificationBarMouseReleased
        String message = "";
        
        if (notifQueue.size() == 0) {
            message = "No recent notifications.";
        } else {
            Iterator i = notifQueue.iterator();
            while (i.hasNext()) {
                message += (String)i.next();
                if (i.hasNext()) message += "\n";
            }
        }
        
        JOptionPane.showMessageDialog(this, message, "Notification Log", JOptionPane.PLAIN_MESSAGE);
    }//GEN-LAST:event_notificationBarMouseReleased

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JScrollPane areaScroll;
    private javax.swing.JTextArea editArea;
    private javax.swing.JFileChooser fileChooser;
    private javax.swing.JTree fileTree;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private javax.swing.JMenuItem menuCommit;
    private javax.swing.JMenuItem menuCopy;
    private javax.swing.JMenuItem menuCut;
    private javax.swing.JMenu menuEdit;
    private javax.swing.JMenuItem menuExit;
    private javax.swing.JMenu menuFile;
    private javax.swing.JMenuItem menuNew;
    private javax.swing.JMenuItem menuOpen;
    private javax.swing.JMenuItem menuPaste;
    private javax.swing.JMenuItem menuPrefs;
    private javax.swing.JMenuItem menuSave;
    private javax.swing.JMenu menuVersion;
    private javax.swing.JLabel notificationBar;
    private javax.swing.JOptionPane optionPane;
    private javax.swing.JScrollPane treeScroll;
    private javax.swing.JScrollPane treeScroll1;
    private javax.swing.JTree userTree;
    // End of variables declaration//GEN-END:variables
}